package service.calculator.jeron;

import java.math.BigDecimal;

import models.Payment;
import models.Rate;
import service.BillingCalculator;
import util.Rounder;

public class JeronBillingCalculatorImpl implements BillingCalculator {
	
	public BigDecimal calculatePayment(Rate rate, Payment payment) {
        BigDecimal paymentCalculation = null;
        JeronPaymentType paymentType = JeronPaymentType
                .valueOf(payment.paymentType);
        final BigDecimal paymentHrs = BigDecimal.valueOf(payment.hours);
        final BigDecimal rateValue = rate.value;

        // 15 per day
        final BigDecimal ecolaRate = BigDecimal.valueOf(1.875);

        switch (paymentType) {
        case BASIC:
        	BigDecimal basicBillingRate = calculateBasicBillingRate(rateValue);
            paymentCalculation = basicBillingRate.multiply(paymentHrs);
            break;
        case HP:
        case HPU:
        case LHRT:
        	// 451 + 15 = 466 (rate + ecola)
        	// 466/8 = 58.25 per hour
        	BigDecimal hpRate = rateValue.add(ecolaRate);
        	paymentCalculation = hpRate.multiply(paymentHrs);
            break;
        case OT:
            BigDecimal otRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.25)));
            paymentCalculation = otRate.multiply(paymentHrs);
            break;
        case LHOT:
            BigDecimal lhotRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(1)));
            lhotRate = lhotRate.add(lhotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = lhotRate.multiply(paymentHrs);
            break;
        case SHRT:
        	BigDecimal shrtRate = rateValue.add(ecolaRate).multiply(BigDecimal.valueOf(0.30));
            paymentCalculation = shrtRate.multiply(paymentHrs);
            break;
        case SUNDAY:
            BigDecimal sundayRate = rateValue.multiply(BigDecimal.valueOf(0.30));
            paymentCalculation = sundayRate.multiply(paymentHrs);
            break;
        case SHOT:
            BigDecimal shotRate = rateValue.add(rateValue.multiply(BigDecimal
                    .valueOf(0.30)));
            shotRate = shotRate.add(shotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = shotRate.multiply(paymentHrs);
            break;
        case RDRT:
            BigDecimal rdrtRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.3)));
            paymentCalculation = rdrtRate.multiply(paymentHrs);
            break;
        case RDOT:
            BigDecimal rdotRate = rateValue.add(rateValue.multiply(BigDecimal
                    .valueOf(0.30)));
            rdotRate = rdotRate.add(rdotRate.multiply(BigDecimal.valueOf(0.30)));
            paymentCalculation = rdotRate.multiply(paymentHrs);
            break;
        case RDLH:
            // Plus 160%
			BigDecimal rdlhRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(1.6)));
            paymentCalculation = rdlhRate.multiply(paymentHrs);
            break;
        case RDSH:
            // Plus 60%
			BigDecimal rdshRate = rateValue.add(rateValue.multiply(BigDecimal.valueOf(0.60)));
            paymentCalculation = rdshRate.multiply(paymentHrs);
            break;
        case NDRT:
            BigDecimal ndrtRate = rateValue.multiply(BigDecimal.valueOf(0.10));
            paymentCalculation = ndrtRate.multiply(paymentHrs);
            break;
        case NDLH:
        	// Only 20% of the rate
			BigDecimal ndlhRate = rateValue.multiply(BigDecimal.valueOf(0.2));
            paymentCalculation = ndlhRate.multiply(paymentHrs);
            break;
        case NDSH:
        	// Only 13% of the rate (10% of rate bec. of ND plus 3% bec. of SH)
			BigDecimal ndshRate = rateValue.multiply(BigDecimal.valueOf(0.13));
            paymentCalculation = ndshRate.multiply(paymentHrs);
            break;
        case TRANSPO:
            // This is money value already
            paymentCalculation = paymentHrs;
            break;
        case ECOLA:
            paymentCalculation = ecolaRate.multiply(paymentHrs);
            break;
        default:
            System.out.println("WARNING: " + payment.paymentType
                    + " payment type not yet supported.");
        }

        if (paymentCalculation != null) {
        	paymentCalculation = Rounder.roundup(paymentCalculation);
        }

        return paymentCalculation;
    }

	private BigDecimal calculateBasicBillingRate(BigDecimal rateValue) {
		BigDecimal basicRate = BigDecimal.valueOf(0.00);
		BigDecimal governmentBenefits = computeGovernmentBenefitsPerHour();

		basicRate = basicRate.add(rateValue);
		basicRate = basicRate.add(governmentBenefits);

		return basicRate;
	}

	protected BigDecimal computeGovernmentBenefitsPerHour() {
		BigDecimal thirteenthMonthPayPerDay = BigDecimal.valueOf(38.83);
		BigDecimal sssPerDay = BigDecimal.valueOf(34.00);
		BigDecimal philhealthPerDay = BigDecimal.valueOf(5.77);
		BigDecimal pagIbigPerDay = BigDecimal.valueOf(3.85);
		BigDecimal ecMcPerDay = BigDecimal.valueOf(0.38);

		BigDecimal governmentBenefits = BigDecimal.valueOf(0.00);
		governmentBenefits = governmentBenefits.add(thirteenthMonthPayPerDay);
		governmentBenefits = governmentBenefits.add(sssPerDay);		
		governmentBenefits = governmentBenefits.add(philhealthPerDay);
		governmentBenefits = governmentBenefits.add(pagIbigPerDay);
		governmentBenefits = governmentBenefits.add(ecMcPerDay);

		governmentBenefits = governmentBenefits.divide(BigDecimal.valueOf(8)); // Compute per hour
		return governmentBenefits;
	}

}
